﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using Tomers.WPF.Shapes;

namespace epk23.PartIIProject
{
    class GraphArrow
    {
        public int type { get; set; }
        public Arrow arrow { get; set; }

        public RuleNode startNode { get; set; }
        public RuleNode endNode { get; set; }

        public int startAnchor { get; set; }
        public int endAnchor { get; set; }

        public GraphArrow(RuleNode startNode, RuleNode endNode, Arrow arrow, int type)
        {
            this.type = type;
            this.startNode = startNode;
            this.endNode = endNode;
            this.startAnchor = startAnchor;
            this.endAnchor = endAnchor;
            this.arrow = arrow;

            //Anchor values:
            //   5  1  6
            //   -------
            // 12|      |7
            //  4|      |2
            // 11|      |8
            //    -------
            //    10 3 9  
            //
            //
            //
            //Arrow type: type 0 is normal arrow for Increment nodes etc and >0 case for decrement nodes.
            //            type 1 is = 0 case for decrement nodes.

            setPosition();
        }

        public void setEndNode(RuleNode endNode)
        {
            this.endNode = endNode;
            setPosition();
        }

        public void setPositionExplicit(double x, double y)
        {
            arrow.X2 = x;
            arrow.Y2 = y;
        }

        public void setPosition()
        {

            double startX = (double)startNode.nodeBody.GetValue(Canvas.LeftProperty);
            double startY = (double)startNode.nodeBody.GetValue(Canvas.TopProperty);
            double endX = (double)endNode.nodeBody.GetValue(Canvas.LeftProperty);
            double endY = (double)endNode.nodeBody.GetValue(Canvas.TopProperty);

            double startHeight = startNode.nodeBody.Height;
            double startWidth = startNode.nodeBody.Width;
            double endHeight = endNode.nodeBody.Height;
            double endWidth = endNode.nodeBody.Width;

            //check for paired arrows

            bool paired = false;
            Rule startRule = ((ConcreteNode)startNode).getRule();
            Rule endRule = ((ConcreteNode)endNode).getRule();

            if (endRule.GetType() == typeof(IncrementRule) || endRule.GetType() == typeof(MachineRule))
            {
                if (endRule.targetRuleNumber == startRule.ruleNumber)
                    paired = true;
            }
            else if (endRule.GetType() == typeof(DecrementRule))
            {
                if (endRule.targetRuleNumber == startRule.ruleNumber || ((DecrementRule)endRule).targetRuleNumber2 == startRule.ruleNumber)
                    paired = true;
            }

            //snapping

            if (startNode == endNode)
            {
                startAnchor = 3;
                endAnchor = 4;

                if (startNode.GetType() == typeof(DecrRuleNode) && type == 1)
                {
                    endAnchor = 2;
                }
            }
            else
            {
                bool above = (startY + startHeight < endY);
                bool left = (startX + startWidth < endX);
                bool below = (startY > endY + endHeight);
                bool right = (startX > endX + endWidth);
                if (above && left)
                {
                    startAnchor = 3;
                    endAnchor = 4;
                }
                else if (above && !left && !right)
                {
                    if (paired)
                    {
                        startAnchor = 9;
                        endAnchor = 6;
                    }
                    else
                    {
                        startAnchor = 3;
                        endAnchor = 1;
                    }
                }

                else if (above && right)
                {
                    if (paired)
                    {
                        startAnchor = 3;
                        endAnchor = 2;
                    }
                    else
                    {
                        startAnchor = 4;
                        endAnchor = 1;
                    }
                }
                else if (right && !above && !below)
                {
                    if (paired)
                    {
                        startAnchor = 11;
                        endAnchor = 8;
                    }
                    else
                    {
                        startAnchor = 4;
                        endAnchor = 2;
                    }
                }
                else if (below && right)
                {
                    startAnchor = 1;
                    endAnchor = 2;
                }
                else if (below && !left && !right)
                {
                    if (paired)
                    {
                        startAnchor = 5;
                        endAnchor = 10;
                    }
                    else
                    {
                        startAnchor = 1;
                        endAnchor = 3;
                    }
                }
                else if (below && left)
                {
                    if (paired)
                    {
                        startAnchor = 1;
                        endAnchor = 4;
                    }
                    else
                    {
                        startAnchor = 1;
                        endAnchor = 4;
                    }
                }
                else if (left && !above && !below)
                {
                    if (paired)
                    {
                        startAnchor = 7;
                        endAnchor = 12;
                    }
                    else
                    {
                        startAnchor = 2;
                        endAnchor = 4;
                    }
                }
            }

            switch (startAnchor)
            {
                case 1:
                    {
                        arrow.X1 = startX + startWidth / 2;
                        arrow.Y1 = startY;
                        break;
                    }
                case 2:
                    {
                        arrow.X1 = startX + startWidth;
                        arrow.Y1 = startY + startHeight / 2;
                        break;
                    }
                case 3:
                    {
                        arrow.X1 = startX + startWidth / 2;
                        arrow.Y1 = startY + startHeight;
                        break;
                    }
                case 4:
                    {
                        arrow.X1 = startX;
                        arrow.Y1 = startY + startHeight / 2;
                        break;
                    }
                case 5:
                    {
                        arrow.X1 = startX + startWidth / 4;
                        arrow.Y1 = startY;
                        break;
                    }
                case 7:
                    {
                        arrow.X1 = startX + startWidth;
                        arrow.Y1 = startY + startHeight / 4;
                        break;
                    }
                case 9:
                    {
                        arrow.X1 = startX + 0.75 * startWidth;
                        arrow.Y1 = startY + startHeight;
                        break;
                    }
                case 11:
                    {
                        arrow.X1 = startX;
                        arrow.Y1 = startY + 0.75 * startHeight;
                        break;
                    }

            }
            switch (endAnchor)
            {
                case 1:
                    {
                        arrow.X2 = endX + endWidth / 2;
                        arrow.Y2 = endY;
                        break;
                    }
                case 2:
                    {
                        arrow.X2 = endX + endWidth;
                        arrow.Y2 = endY + endHeight / 2;
                        break;
                    }
                case 3:
                    {
                        arrow.X2 = endX + endWidth / 2;
                        arrow.Y2 = endY + endHeight;
                        break;
                    }
                case 4:
                    {
                        arrow.X2 = endX;
                        arrow.Y2 = endY + endHeight / 2;
                        break;
                    }
                case 6:
                    {
                        arrow.X2 = endX + 0.75 * endWidth;
                        arrow.Y2 = endY;
                        break;
                    }
                case 8:
                    {
                        arrow.X2 = endX + endWidth;
                        arrow.Y2 = endY + 0.75 * endWidth;
                        break;
                    }
                case 10:
                    {
                        arrow.X2 = endX + endWidth / 4;
                        arrow.Y2 = endY + endHeight;
                        break;
                    }
                case 12:
                    {
                        arrow.X2 = endX;
                        arrow.Y2 = endY + endWidth / 4;
                        break;
                    }
            }
        }
    }
}
